﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Entity;
using AdventureWorks.DAO;
using System.Data;
using System.Linq.Expressions;
using AdventureWorks.Entities;

namespace AdventureWorksData.DAO
{
	public class GenericRepository<T> : IGenericRepository<T> where T : Entity
	{
		private readonly IDbSet<T> _db;
		private readonly DbContext _context;

		public GenericRepository()
		{
			_context = new AdventureWorksContext();
			_db = _context.Set<T>();
		}
		
		public GenericRepository(DbContext context, IDbSet<T> db )
		{
			_context = context;
			_db = db;
		}

		public void Delete(int id)
		{
			T entity = _db.Single(i => i.ID == id);
			Delete(entity);
		}

		public void Delete(T entityToDelete)
		{
			if (_context.Entry(entityToDelete).State == EntityState.Detached)
				_db.Attach(entityToDelete);

			_db.Remove(entityToDelete);
		}

		public IEnumerable<T> Get(
			Expression<Func<T, bool>> filter = null, 
			Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, 
			string includeProperties = "")
		{
			IQueryable<T> query = _db;

			if (filter != null)
				query = query.Where(filter);

			foreach (var includeProperty in includeProperties.Split(new char[]{','}, StringSplitOptions.RemoveEmptyEntries))
			{
				query = query.Include(includeProperty);
			}

			return orderBy != null ? orderBy(query).ToList() : query.ToList();
		}

		public T Get(int id)
		{
			var t = _db.Single(i => i.ID == id);
			return t;
		}

		public void Insert(T entity)
		{
			_db.Add(entity);
		}

		public void Update(T entityToUpdate)
		{
			_db.Attach(entityToUpdate);
			_context.Entry(entityToUpdate).State = EntityState.Modified;
		}

		public void Dispose()
		{
			throw new NotImplementedException();
		}
	}
}
